﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace FirstFloor.Reversi.Controls
{
    public class Button
        : ControlBase
    {
        /// <summary>
        /// Occurs when the button is clicked.
        /// </summary>
        public event EventHandler<EventArgs> Click;

        private TextBlock text;
        private Rectangle border;
        private TranslateTransform pressedTransform;
        private bool buttonPressed = false;
        private bool mouseOver = false;

        /// <summary>
        /// Initializes a new instance of the <see cref="Button"/> class.
        /// </summary>
        public Button()
        {
            this.text = (TextBlock)FindName("text");
            this.border = (Rectangle)FindName("border");
            this.pressedTransform = (TranslateTransform)FindName("pressedTransform");

            Control.MouseEnter += new MouseEventHandler(OnMouseEnter);
            Control.MouseLeave += new EventHandler(OnMouseLeave);
            Control.MouseLeftButtonDown += new MouseEventHandler(OnMouseLeftButtonDown);
            Control.MouseLeftButtonUp += new MouseEventHandler(OnMouseLeftButtonUp);
            RootLeave += new EventHandler(OnRootLeave);

            UpdateVisuals();
        }

        /// <summary>
        /// Gets or sets the background.
        /// </summary>
        /// <value>The background.</value>
        public Brush Background
        {
            get { return this.border.Fill; }
            set { this.border.Fill = value; }
        }

        /// <summary>
        /// Gets or sets the border.
        /// </summary>
        /// <value>The background.</value>
        public Brush Border
        {
            get { return this.border.Stroke; }
            set { this.border.Stroke = value; }
        }

        /// <summary>
        /// Gets or sets the text.
        /// </summary>
        /// <value>The text.</value>
        public string Text
        {
            get { return this.text.Text; }
            set
            {
                this.text.Text = value;
                UpdateLayout();
            }
        }
        /// <summary>
        /// Called when the element is loaded or Width or Height is changed. The base implementation does nothing.
        /// </summary>
        protected override void UpdateLayout()
        {
            this.border.Width = Width;
            this.border.Height = Height;

            this.text.SetValue<double>(Canvas.LeftProperty, Width / 2 - this.text.ActualWidth / 2);
            this.text.SetValue<double>(Canvas.TopProperty, Height / 2 - this.text.ActualHeight / 2);
        }

        /// <summary>
        /// The resource name containg the xaml used to initialize the actual object
        /// </summary>
        /// <value></value>
        protected override string XamlResourceName
        {
            get { return "FirstFloor.Reversi.Source.Controls.Button.xaml"; }
        }

        private void UpdateVisuals()
        {
            //Control.Opacity = this.mouseOver ? 1 : .7;
            this.pressedTransform.X = this.buttonPressed ? 1 : 0;
            this.pressedTransform.Y = this.buttonPressed ? 1 : 0;
        }

        private void OnMouseLeftButtonDown(object sender, MouseEventArgs args)
        {
            Control.CaptureMouse();
            this.mouseOver = true;
            this.buttonPressed = true;
            UpdateVisuals();
        }

        private void OnMouseLeftButtonUp(object sender, MouseEventArgs args)
        {
            if (this.mouseOver && Click != null) {
                Click(this, EventArgs.Empty);
            }

            ReleaseMouseCapture();
            this.buttonPressed = false;
            UpdateVisuals();
        }

        private void OnMouseEnter(object sender, MouseEventArgs args)
        {
            this.mouseOver = true;
            UpdateVisuals();
        }

        private void OnMouseLeave(object sender, EventArgs args)
        {
            this.mouseOver = false;
            UpdateVisuals();
        }

        private void OnRootLeave(object sender, EventArgs args)
        {
            if (this.mouseOver || this.buttonPressed) {
                ReleaseMouseCapture();
                this.mouseOver = false;
                this.buttonPressed = false;
                UpdateVisuals();
            }
        }
    }
}
